/**
 * 
 */
package de.fsujena.chat_pi.server;

import java.io.*;
import java.util.Date;

import de.fsujena.chat_pi.message.SysMessage;
import de.fsujena.chat_pi.message.SysMessage.CATEGORY;
import de.fsujena.chat_pi.message.SysMessage.MESSAGE;
import de.fsujena.chat_pi.server.user.UserManager;
import de.fsujena.chat_pi.server.userInterface.ConsoleUI;
import de.fsujena.chat_pi.server.userInterface.UserInterface;;

/**
 * Server implementation. It holds user and room manager and starts a network listener on 
 * a specific port. It also offers methods to display messages for the server.
 * 
 * @author Erik Hebestreit
 */
public class Server {
	
	public UserManager userManager;
	public NetworkListener networkListener;
	public boolean isStarted=false;
	BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
	UserInterface ui;
	
	private int port = 3141;

	/**
	 * @param args port can optionally be specified
	 * @throws IOException 
	 */
	public static void main(String[] args) {
		// create a new instance of the server object
		new Server().initServer(args);
	}
	
	/**
	 * Constructor. It launches the user manager and the network listener.
	 * 
	 * @param args arguments forwarded from main()
	 */
	public void initServer(String[] args) {
		// initialize user interface
		ui = new ConsoleUI(this);
		new Thread(ui).start();
		
		// initialize user manager
		ui.postInfo("Welcome");
		userManager = new UserManager(this);
		
		//startNetworkListener(args);
		
		if (args.length >= 1) {
			startNetworkListener(args);
			this.isStarted = true;
		}
		
		/*while (true) {
			String cmd = null;
			try {
				cmd = input.readLine();		//read from console

			} catch (Exception e) {
				e.printStackTrace();

			}

			if (cmd.startsWith("$")) {		//checks if input is a command
				// check the command
				commander(cmd);				//yes? call commander
			}else {
				sendTextMessage(cmd);
				}
			
		}*/
	}
	
	
	public void startNetworkListener(String[] args) {
		// if port is specified by input argument, it is set - else the default port stays set
		if (args.length > 0) {
			try {
				if (!this.setPort(Integer.parseInt(args[0]))) // if parsed integer is not a valid port number (checked in setPort)
					ui.postWarning(String.format("Port %i is not valid. Default port %i used instead.", Integer.parseInt(args[0]), this.getPort()));
		    } catch (NumberFormatException e) {
		    	ui.postWarning("Argument must be an integer.");
		    }
		}
		
		try {
			// launch network listener on specific port
			networkListener = new NetworkListener(this.getPort(),this);
			
			/*
			 *  start network listener thread which handles login, registration and
			 *  listens for conventional messages
			 */
			networkListener.start();
			
			ui.postInfo(String.format("server started on port %d",this.getPort()));
		} catch (IOException e) {e.printStackTrace();}
	}
	
	/**
	 * Set the port. Note that this setting only takes effect for a newly created NetworkListener.
	 * 
	 * @param port port number where the server should listen
	 * @return <b>true</b> if port was set successfully,
	 * <b>false</b> if port number exceeded possible port numbers
	 */
	public boolean setPort(int port) {
		if (port > 1024 && port <= 65535) {
			this.port = port;
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Get the currently set port.
	 * 
	 * @return port number where the server is listening
	 */
	public int getPort() {
		return this.port;
	}
	
	
	
	

	/**
	 * closes the server and cancels the connection
	 */
	public void stopServer(){
		SysMessage tempMsg=new SysMessage(CATEGORY.CONNECTION,MESSAGE.SERVER_CLOSED);
		tempMsg.setSenderUsername("SERVER");
		tempMsg.setSent(new Date());
		networkListener.distributeMsg(tempMsg);											//tell the clients that the server shuts down
		networkListener.close();														//removes connections
		networkListener=null;															//free resources
		ui.postInfo("server is closed");													//post info
		isStarted=false;
		return;
	}

	/**
	 * starts the server
	 * 
	 * @param portstr String containing the port number
	 */
	public void startServer(String portstr){
		String[] temp=new String[1];			//needed because startNetworkListener requires an array
		temp[0]=portstr;
		startNetworkListener(temp);
		isStarted=true;
		return;
	}

	/**
	 * closes the program
	 */
	public void exit(){
		if (isStarted)
			stopServer();					//at first cancel connection
		
		System.exit(0);						//stop the main thread
	}
}
